// Copyright (c) 2015
// Author: Chrono Law
#include <std.hpp>
using namespace std;

#include <boost/assign.hpp>
#include <boost/multi_array.hpp>
using namespace boost;

//////////////////////////////////////////
void case1() {
    multi_array<int, 3> ma(extents[2][3][4]);

    auto shape = ma.shape();
    for (size_t i = 0; i < ma.num_dimensions(); ++i) {
        cout << shape[i] << ",";
    }
    cout << endl << ma.num_elements() << endl;

    for (int i = 0, v = 0; i < 2; ++i)
        for (int j = 0; j < 3; ++j)
            for (int k = 0; k < 4; ++k) {
                ma[i][j][k] = v++;
            }

    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 3; ++j) {
            for (int k = 0; k < 4; ++k) {
                cout << ma[i][j][k] << ",";
            }
            cout << endl;
        }
        cout << endl;
    }

    // cout << ma[2][3][4];

    std::array<size_t, 3> idx = {0, 1, 2};
    ma(idx) = 10;
    cout << ma(idx) << endl;
}

//////////////////////////////////////////
void case2() {
    multi_array<int, 3> ma(extents[2][3][4]);
    assert(ma.shape()[0] == 2);

    std::array<std::size_t, 3> arr = {4, 3, 2};
    ma.reshape(arr);
    assert(ma.shape()[0] == 4);

    ma.resize(extents[2][9][9]);
    assert(ma.num_elements() == 2 * 9 * 9);
    assert(ma.shape()[1] == 9);
}

//////////////////////////////////////////
void case3() {
    typedef multi_array<int, 2> ma_type;
    multi_array<int, 2> ma(extents[3][4]);

    typedef ma_type::index_range range;
    // indices[range(0,2)][range(0,2)];

    auto view = ma[indices[range(0, 2)][range(0, 2)]];

    cout << view.num_elements() << endl;
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 2; ++j) {
            cout << view[i][j] << ",";
        }
        cout << endl;
    }
    cout << *view.shape() << endl;
}

//////////////////////////////////////////
void case4() {
    int arr[12];
    for (int i = 0; i < 12; ++i) {
        arr[i] = i;
    }

    multi_array_ref<int, 2> mar(arr, extents[3][4]);

    for (size_t i = 0; i < 3; ++i) {
        cout << "(";
        for (size_t j = 0; j < 4; ++j) {
            cout << mar[i][j]++;
            cout << (j != 3 ? ',' : ' ');
        }
        cout << ")" << endl;
    }

    const_multi_array_ref<int, 2> cmar(arr, extents[2][6]);

    for (size_t i = 0; i < 2; ++i) {
        cout << "(";
        for (size_t j = 0; j < 6; ++j) {
            cout << cmar[i][j];
            cout << (j != 5 ? ',' : ' ');
        }
        cout << ")" << endl;
    }
}

//////////////////////////////////////////
void case5() {
    // multi_array<int, 3> ma(vector<int>(assign::list_of(2)(2)));
    multi_array<int, 3> ma(vector<int>{2, 2, 2});
    auto shape = ma.shape();
    for (size_t i = 0; i < ma.num_dimensions(); ++i) {
        cout << shape[i] << ",";
    }
}

//////////////////////////////////////////
void case6() {
    typedef multi_array<int, 3> ma_type;
    typedef ma_type::extent_range range;
    ma_type ma(extents[range(1, 5)][4][range(-2, 2)]);
    ma[1][0][-2] = 10;

    ma.reindex(1);
    assert(ma[1][1][1] == 10);
    ma.reindex(std::array<int, 3>{1, 0, -4});
    assert(ma[1][0][-4] == 10);

    cout << *ma.index_bases() << endl;
}
//////////////////////////////////////////
void case7() {
    using namespace boost::detail::multi_array;

    typedef multi_array<int, 3> ma_type;
    typedef ma_type::index_range range;
    ma_type ma(extents[9][8][7]);

    // auto view = ma[indices[range() < 3L][2L <= range() <= 5L][range()]];
    // cout << *view.shape() << endl;
}
//////////////////////////////////////////
void case8() {
    using namespace boost::detail::multi_array;

    const int N = 3; // N must be const
    typedef multi_array<int, N> ma_type;
    typedef ma_type::index_range range;
    ma_type ma(extents[9][8][7]);

    int ndims = ma.num_dimensions();
    auto shape = ma.shape();
    for (int i = 0; i < ndims; i++) {
        std::cout << shape[i] << std::endl;
    }
}

void print_non_zero_ranges(const boost::multi_array<float, 2> &array) {
    // 获取数组的形状
    // auto shape = array.shape();

    // auto sub_array = array[0];

    // // 遍历每个维度，查找非0元素的范围
    // for (size_t dim = 0; dim < array.num_dimensions(); ++dim) {
        // auto itr_begin = array[dim].begin();
        // auto itr_end = array[dim].end();

        // // 跳过前面的0元素
        // while (itr_begin != itr_end && *itr_begin == 0) {
        //     ++itr_begin;
        // }

        // // 跳过尾部的0元素
        // while (itr_end != itr_begin && *(itr_end - 1) == 0) {
        //     --itr_end;
        // }
        // auto A = array[dim];
        // for (size_t i = 0; i < A.num_elements(); ++i) {
        //     if (A.element(i)) {  // 如果 element(i) 返回的是 bool 类型，则直接使用
        //         std::cout << "Element is non-zero at index: " << A.shape() << std::endl;
        //     }
        // }
        // auto itr_begin = array[dim].begin();
        // auto itr_end = array[dim].end();

        // // 跳过前面的0元素
        // while (itr_begin != itr_end && *itr_begin == 0) {
        //     ++itr_begin;
        // }

        // // // 输出非0元素的范围
        // std::cout << "Dimension " << dim << ": [" << itr_begin - array[dim].begin() << ", "
        //           << (itr_end - array[dim].begin()) << "]" << std::endl;
        // break;
    // }
}
void case9() {
    // 创建一个示例的multi_array
    typedef boost::multi_array<float, 2> array_type;
    array_type array(boost::extents[3][5]);
    array[0][0] = 1;
    array[0][1] = 0;
    array[0][2] = 2;
    array[0][3] = 0;
    array[0][4] = 3;
    array[1][0] = 0;
    array[1][1] = 4;
    array[1][2] = 0;
    array[1][3] = 5;
    array[1][4] = 0;
    array[2][0] = 6;
    array[2][1] = 0;
    array[2][2] = 7;
    array[2][3] = 0;
    array[2][4] = 8;

    // 打印每个维度非0元素的范围
    print_non_zero_ranges(array);
}

//////////////////////////////////////////

int main() {
    // case1();
    // case2();
    // case3();
    // case4();
    // case5();
    // case6();
    case7();
    // case8();
    // case9();
}
